﻿#include"game.h"

//void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
//{
//	int i = 0; 
//	for (i = 0; i < rows; i++)
//	{
//		int j = 0;
//		for (j = 0; j < cols; j++)
//		{
//			board[i][j] = set;
//		}
//	}
//}
//
//void DisplayBoard(char board[ROWS][COLS], int row, int col)
//{
//	printf("------ 扫雷游戏 ------\n");
//	for (int i = 0; i <= col; i++)
//		printf("%d ", i);
//	printf("\n");
//	for (int i = 1; i <= row; i++)
//	{
//		printf("%d ", i);
//		for (int j = 1; j <= col; j++)
//			printf("%c ", board[i][j]);
//		printf("\n");
//	}
//}
//
//void SetMine(char board[ROWS][COLS], int row, int col)
//{
//	int x = 0, y = 0;
//	int count = MINE_COUNT;
//	while(count)
//	{
//		x = rand() % row + 1;
//		y = rand() % col + 1;
//		if (board[x][y] == '0')
//		{
//			board[x][y] += 1;
//			count--;
//		}
//	}
//}
//
//int dx[8] = { 1,-1,0,0,-1,-1,1,1 };
//int dy[8] = { 0,0,1,-1,-1,1,-1,1 };
//int GetCount(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
//{
//	return (mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1]
//		+ mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0');
//}
//void dfs(char mine[ROWS][COLS], char show[ROWS][COLS], int i, int j,int row,int col,int* count)
//{
//	if (mine[i][j] == '1'||GetCount(mine,show,i,j)!=0) return;
//	show[i][j] = '0' + GetCount(mine, show, i, j);
//	for (int k = 0; k < 8; k++)
//	{
//		int x = dx[k] + i;
//		int y = dy[k] + j;
//		if (x >= 1 && x <= row && y >= 1 && y <= col && show[x][y] == '*' && GetCount(mine, show, i, j) == 0)
//		{
//			(*count)--;
//			dfs(mine, show, x, y, row, col, count);
//		}
//	}
//}
//void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
//{
//	int x, y;
//	int count = row * col - MINE_COUNT;
//	while (count--)
//	{
//		printf("请输入你要排的坐标：");
//		scanf("%d %d", &x, &y);
//		if (x > 0 && x <= row && y > 0 && y <= col)
//		{
//			if (mine[x][y] == '1')
//			{
//				printf("这是雷，你被炸死了\n");
//				DisplayBoard(mine, row, col);
//				return;
//			}
//			else
//			{
//				show[x][y]='0'+GetCount(mine, show, x, y);
//				dfs(mine, show, x, y,row,col,&count);
//				//for (int k = 0; k < 8; k++)
//				//{
//				//	x += dx[k];
//				//	y += dy[k];
//				//}
//				DisplayBoard(show, row, col);
//			}
//		}
//		else
//			printf("输入的坐标不存在，请重新输入\n");
//	}
//	printf("恭喜你，成功排出所有雷\n");
//}

#include"game.h"

void SetPos(short x, short y)
{
	COORD pos = { x, y };
	HANDLE hOutput = NULL;
	//获取标准输出的句柄(?来标识不同设备的数值)
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	//设置标准输出上光标的位置为pos
	SetConsoleCursorPosition(hOutput, pos);
}
void WelcomeToGame()
{
	SetPos(40, 15);
	printf("欢迎来到贪吃蛇小游戏");
	SetPos(40, 25);
	system("pause");
	system("cls");
	SetPos(25, 12);
	printf("? ↑ . ↓ . ← . → 分别控制蛇的移动， F3为加速，F4为减速\n");
	SetPos(25, 13);
	printf("加速能获得更高的分数\n");
	SetPos(40, 25);
	system("pause");
	system("cls");
}
void CreateMap()
{
	//打印第一行
	int i = 0;
	SetPos(0, 0);
	for (i = 0; i < 58; i += 2)
	{
		wprintf(L"%lc", Wall);
	}
	//打印最后一行
	SetPos(0, 26);
	for (i = 0; i < 58; i += 2)
	{
		wprintf(L"%lc", Wall);
	}
	//打印第一列和最后一列
	for (i = 1; i < 26; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc", Wall);
		SetPos(56, i);
		wprintf(L"%lc", Wall);
	}
}
void InitSnake(pSnake ps)
{
	pSnakeNode cur = NULL;
	for (int i = 0; i < 5; i++)
	{
		cur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (cur == NULL)
		{
			perror("InitSnake error\n");
			return;
		}
		cur->next = NULL;
		cur->x = Pos_x + i * 2;
		cur->y = Pos_y ;
		if (ps->_pSnake == NULL)
		{
			ps->_pSnake = cur;
		}
		else
		{
			cur->next = ps->_pSnake;
			ps->_pSnake = cur;
		}
	}
	//打印蛇身
	cur = ps->_pSnake;
	while (cur!=NULL)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", Body);
		cur = cur->next;
	}

	//初始化贪吃蛇的数据
	ps->_dir = RIGHT;
	ps->_FoodWeight = 10;
	ps->_Score = 0;
	ps->_Sleeptime = 200;  //单位：毫秒
	ps->_status = OK;

}
void CreateFood(pSnake ps)
{
	int x1 = 0;
	int y1 = 0;
again:
	do
	{
		x1 = rand() % 53 + 2;
		y1 = rand() % 25 + 1;
	} while (x1 % 2 != 0);

	pSnakeNode tmp= ps->_pSnake;
	while (tmp)
	{
		if (tmp->x == x1 && tmp->y == y1)
			goto again;
		tmp = tmp->next;
	}

	//生成食物成功
	tmp = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (tmp == NULL) {
		// 处理内存分配失败的情况
		perror("malloc failed");
		return;
	}
	tmp->next = NULL;
	tmp->x = x1;
	tmp->y = y1;
	ps->_pFood = tmp;
	
	//打印食物
	SetPos(x1, y1);
	wprintf(L"%lc", Food);
}
void GameInit(pSnake ps)
{
	ps->_pSnake = NULL;
	ps->_pFood = NULL;
	//1.设置窗口大小和光标信息
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO CursorInfo;
	GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
	CursorInfo.bVisible = false;
	SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态

	//2.打印欢迎界面和功能介绍
	WelcomeToGame();
	//3.绘制地图
	CreateMap();
	//4.创建蛇
	InitSnake(ps);
	//5.创建食物
	CreateFood(ps);
}


void PrintRightInfo()
{
	//打印提⽰信息
	SetPos(64, 15);
	printf("不能穿墙，不能咬到⾃⼰\n");
	SetPos(64, 16);
	printf("⽤↑.↓.←.→分别控制蛇的移动.");
	SetPos(64, 17);
	printf("F3 为加速，F4 为减速\n");
	SetPos(64, 18);
	printf("ESC ：退出游戏.space：暂停游戏.");
	//SetPos(64, 20);
	//printf("zwt make it");
}
void Pause()
{
	while (1)
	{
		Sleep(300);
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
	}
}
bool isFood(pSnake ps, pSnakeNode pNextNode)
{
	return (ps->_pFood->x == pNextNode->x) && (ps->_pFood->y == pNextNode->y);
}
void EatFood(pSnake ps, pSnakeNode pNextNode)
{
	pNextNode->next = ps->_pSnake;
	ps->_pSnake = pNextNode;

	pSnakeNode cur = ps->_pSnake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%c", Body);
		cur = cur->next;
	}
	ps->_Score += ps->_FoodWeight;

	//释放⻝物节点
	free(ps->_pFood);
	//创建新的⻝物
	CreateFood(ps);
}
void NoFood(pSnake ps, pSnakeNode pNextNode)
{
	pNextNode->next = ps->_pSnake;
	ps->_pSnake = pNextNode;

	pSnakeNode cur = ps->_pSnake;
	while (cur->next->next)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", Body);
		cur = cur->next;
	}

	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	cur->next = NULL;
	free(cur->next);
	//cur->next = NULL;
}
int KillByWall(pSnake ps)
{
	if ((ps->_pSnake->x == 0)
		|| (ps->_pSnake->x == 56)
		|| (ps->_pSnake->y == 0)
		|| (ps->_pSnake->y == 26))
	{
		ps->_status = KILL_BY_WALL;
		return 1;
	}
	return 0;
}
int KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pSnake->next;
	while (cur)
	{
		if ((ps->_pSnake->x == cur->x)
			&& (ps->_pSnake->y == cur->y))
		{
			ps->_status = KILL_BY_SELF;
			return 1;
		}
		cur = cur->next;
	}
	return 0;
}
void SnakeMove(pSnake ps)   //蛇身移动
{
	pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(pSnakeNode));
	if (pNextNode == NULL)
	{
		perror("pNextNode malloc error\n");
		return;
	}
	switch (ps->_dir)
	{
	case UP:
	{
		pNextNode->x = ps->_pSnake->x;
		pNextNode->y = ps->_pSnake->y - 1;
	}
	break;
	case DOWN:
	{
		pNextNode->x = ps->_pSnake->x;
		pNextNode->y = ps->_pSnake->y + 1;
	}
	break;
	case LEFT:
	{
		pNextNode->x = ps->_pSnake->x-2;
		pNextNode->y = ps->_pSnake->y;
	}
	break;
	case RIGHT:
	{
		pNextNode->x = ps->_pSnake->x+2;
		pNextNode->y = ps->_pSnake->y;
	}
	break;
	}

	//有没有食物
	if (isFood(ps, pNextNode))
	{
		EatFood(ps, pNextNode);
	}
	else
	{
		NoFood(ps, pNextNode);
	}

	KillByWall(ps);
	KillBySelf(ps);
}
//开始游戏
void GameRun(pSnake ps)
{
	//打印右侧帮助信息
	PrintRightInfo();
	do
	{
		SetPos(64, 10);
		printf("得分：%d ", ps->_Score);
		printf("每个食物得分：%2d分", ps ->_FoodWeight);
		if (KEY_PRESS(VK_UP) && ps->_dir != DOWN)
		{
			ps->_dir = UP;
		}
		else if (KEY_PRESS(VK_DOWN) && ps->_dir != UP)
		{
			ps->_dir = DOWN;
		}
		else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT)
		{
			ps->_dir = LEFT;
		}
		else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT)
		{
			ps->_dir = RIGHT;
		}
		else if (KEY_PRESS(VK_SPACE))
		{
			Pause();
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->_status = END_NOMAL;
		}
		else if (KEY_PRESS(VK_F3))
		{
			if (ps->_Sleeptime > 180)
			{
				ps->_Sleeptime -= 30;
				ps->_FoodWeight += 2;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			if (ps->_Sleeptime < 320)
			{
				ps->_Sleeptime += 30;
				ps->_FoodWeight -= 2;
			}
		}
		Sleep(ps->_Sleeptime);
		SnakeMove(ps);
	} while (ps->_status == OK);
}

void GameEnd(pSnake ps)
{
	pSnakeNode cur = ps->_pSnake;
	SetPos(24, 12);
	switch (ps->_status)
	{
	case END_NOMAL:
		printf("正确退出游戏\n");
		break;
	case KILL_BY_SELF:
		printf("你撞到了自己\n");
		break;
	case KILL_BY_WALL:
		printf("你撞到了墙上\n");
		break;
	}

	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		del = NULL;
		free(del);
	}
}